package excise;

import java.util.ArrayList;
import java.util.concurrent.RecursiveTask;

/**
 * @author CoderXshuai
 */
public class PrimThread extends RecursiveTask<Long> {
    private final long end;
    private long begin;
    private long time;
    static Object object=new Object();

    public PrimThread(long begin, long end) {
        this.begin = begin;
        this.end = end;
    }

    @Override
    protected Long compute() {
        long startTime = System.currentTimeMillis();
        long sum = 0;
        ArrayList<PrimThread> primThreads = new ArrayList<>();
        if (end - begin + 1 <= 100) {
            while (begin <= end) {
                if (isPrime(begin)) {
                    sum += begin;
                }
                begin++;
            }
        } else {
            //如果工作量很大，需要分组
            //gap表示每一小组开头和结尾的间隔，假设我先分成100组
            long gap = (end - begin + 1) / 100;
            //表示第一个小组的开头
            long start = begin;
            //对100个小组分别获取其开头和结尾
            for (int i = 0; i < 100; i++) {
                //结尾=将开头加上间隔
                long last = start + gap;
                //当最后一组的结尾达到给定数字的最大值，直接将结尾表示为最大值
                if (last > end) {
                    last = end;
                }
                //新建一个线程执行当前小组的任务
                PrimThread primThread = new PrimThread(start, last);
                //将当前线程加入到列表中，便于后面一次性全部执行
                primThreads.add(primThread);
                //下一个小组的开头等于当前小组的结尾+1
                start = last + 1;
            }
        }
        //invokeAll()表示执行参数中的所有线程中的任务
        invokeAll(primThreads);
        //最后通过插队的方式使得，获取到每个小组中的返回的参数，然后将其累加
        for (PrimThread t : primThreads) {
            sum += t.join();
        }
        long endTime = System.currentTimeMillis();
        time += (endTime - startTime);
        return sum;
    }

    public boolean isPrime(long number) {
        if (number == 1) {
            return false;
        }
        for (int i = 2; i <= Math.sqrt(number); i++) {
            if (number % i == 0) {
                return false;
            }
        }
        return true;
    }

    public long getTime() {
        return time;
    }

    public void setTime(long time) {
        this.time = time;
    }
}
